package cn.stazxr.core.interceptor;

import cn.stazxr.annotation.Repeat;
import cn.stazxr.config.CustomObjectMapper;
import cn.stazxr.core.RedisTemplate;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.lang.reflect.Method;
import java.time.Duration;

import static cn.stazxr.constants.HttpConstant.AUTHORIZATION;
import static cn.stazxr.constants.RedisKeyConstant.REPEAT_SUBMIT_KEY;

/**
 * @author talentestors
 * @version 1.0
 * @since 2025.11.06
 **/
@Slf4j
@Component
public class RepeatSubmitInterceptor implements HandlerInterceptor {
	@Autowired
	private RedisTemplate redisTemplate;

	@Autowired
	private CustomObjectMapper customObjectMapper;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		if (handler instanceof HandlerMethod handlerMethod) {
			// 获取我们的controller方法
			Method method = handlerMethod.getMethod();
			// 判断是否有防止重复提交的注解
			Repeat annotation = method.getAnnotation(Repeat.class);
			if (annotation != null) {
				if (this.isRepeatSubmit(request, annotation)) {
					// 如果确定是重复提交，直接响应失败
					ResponseEntity<String> body = ResponseEntity.status(500).body("您重复提交了当前的请求！");
					response.setStatus(500);
					response.setContentType("application/json;charset=utf-8");
					log.info("{}", body);
					response.getWriter().write(customObjectMapper.writeValueAsString(body));
					return false;
				}
			}
		}
		return true;
	}

	public boolean isRepeatSubmit(HttpServletRequest request, Repeat annotation) throws IOException {
		// 获取参数列表，并序列化
		String nowParams = customObjectMapper.writeValueAsString(request.getParameterMap());

		// 请求地址（作为存放cache的key值）
		String url = request.getRequestURI();

		// 唯一值（没有消息头则使用请求地址）
		String token = request.getHeader(AUTHORIZATION);

		// 获得body的数据

		// 唯一标识（指定key + url + 消息头）
		String cacheRepeatKey = REPEAT_SUBMIT_KEY + token + ":" + url;
		// 如果redis中没有存在这个key，说明这个请求不是重复提交
		String preParams = redisTemplate.get(cacheRepeatKey);

		if (preParams != null && preParams.equals(nowParams)) {
			return true;
		}
		// 否则我就存入redis，注意设置过期时间
		redisTemplate.set(cacheRepeatKey, Duration.ofSeconds(annotation.value()), nowParams);
		return false;
	}
}
